package cz.najman.emdroid.ui;

import java.text.SimpleDateFormat;
import java.util.Date;

import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;

import com.markupartist.android.widget.ActionBar;

import cz.najman.emdroid.R;
import cz.najman.emdroid.helper.EventHelper;
import cz.najman.emdroid.helper.PaymentInformationHelper;
import cz.najman.emdroid.helper.RegistrationStateHelper;
import cz.najman.emdroid.listener.ActionBarOnDataUpdatedListener;
import cz.najman.emdroid.mappings.Event;
import cz.najman.emdroid.mappings.PaymentInformation;
import cz.najman.emdroid.mappings.PaymentValue;
import cz.najman.emdroid.mappings.RegistrationState;
import cz.najman.emdroid.mappings.StornoValue;
import cz.najman.emdroid.utils.WhereClauseBuilder;

/**
 * @author Lukáš Najman
 */
public class EventDetailsActivity extends ActionBarActivity {

	private static final String TAG = "EventDetailsActivity";

	/**
	 * Key intended to be used in the intent extra to signalize what
	 * informations about event to show. Possible values are:
	 * SHOW_EVENT_WITH_REGISTARTION_STATE which shows event informations along
	 * with registration state belonging to this event and user which USER_ID
	 * was supplied in the intent.
	 */
	public static final String ACTION_TYPE = "action_type";

	/**
	 * Value used with ACTION_TYPE key in the intent. You also need to supply
	 * the USER_ID and EVENT_ID in the intent.
	 */
	public static final int SHOW_EVENT_WITH_REGISTARTION_STATE = 1;

	/**
	 * Value used with ACTION_TYPE key in the intent. You also need to supply
	 * the USER_ID and EVENT_ID in the intent.
	 */
	public static final int SHOW_EVENT_TO_REGISTER = 2;

	/**
	 * Value used with ACTION_TYPE key in the intent. You also need to supply
	 * the EVENT_ID in the intent.
	 */
	public static final int SHOW_EVENT_BASIC_INFORMATIONS = 3;

	private TextView tvEventName, tvRegState, tvStartDate, tvEndDate,
			tvRegStartDate, tvRegEndDate;
	private Button btRegister;
	private TableLayout tbPaymentInfo, tbStornoInfo;

	private Cursor mEvent, mPaymentValues, mStornoValues;

	private EMDroidApplication mApplication;
	private PaymentInformationHelper mPaymentInformationHelper;
	private EventHelper mEventHelper;
	private RegistrationStateHelper mRegistrationStateHelper;

	private LayoutInflater mLayoutInflater;
	private SimpleDateFormat mSdf;
	private WhereClauseBuilder mWCB;

	// variables used to identify the informations to display
	int mEventId, mUserId;
	int mInformationToShow = SHOW_EVENT_BASIC_INFORMATIONS;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// Get the intent that stared this activity
		Intent startIntent = getIntent();

		// Extract the extras from the start Intent
		mEventId = startIntent.getIntExtra("eventId", -1);
		mUserId = startIntent.getIntExtra("userId", -1);
		mInformationToShow = startIntent.getIntExtra(ACTION_TYPE,
				SHOW_EVENT_BASIC_INFORMATIONS);

		setupBasicGui();

		/* Get the needed application references */
		mApplication = (EMDroidApplication) getApplication();
		mPaymentInformationHelper = mApplication.getPaymentInformationHelper();
		mEventHelper = mApplication.getEventHelper();
		mRegistrationStateHelper = mApplication.getRegistrationStateHelper();

		mWCB = WhereClauseBuilder.getInstance();
		mSdf = new SimpleDateFormat("dd.MM. yyyy HH:mm");
		mLayoutInflater = getLayoutInflater();
	}

	@Override
	protected void onStart() {
		Cursor event = queryEventData();
		fillEventInformations(event);
		queryPaymentValues();
		fillPaymentInfrormationsTable(tbPaymentInfo, mPaymentValues);
		fillPaymentInfrormationsTable(tbStornoInfo, mStornoValues);

		super.onStart();
	}

	@Override
	protected void onResume() {
		mPaymentInformationHelper.registerListener(
				PaymentInformation.class.getCanonicalName(),
				new OnPaymentInformationUpdatedListener(mActionBar));
		mEventHelper.registerListener(Event.class.getCanonicalName(),
				new onEventInfromationUpdatedListener(mActionBar));
		mRegistrationStateHelper.registerListener(
				RegistrationState.class.getCanonicalName(),
				new onRegistrationStateUpdatedListener(mActionBar));

		/*
		 * If the event id is not -1, update Event informations from remote
		 * server
		 */
		if ((mEventId != -1) && (mUserId != -1)) {
			mEventHelper.retrieveEvent(mEventId);
		}

		super.onResume();
	}

	@Override
	protected void onPause() {
		mPaymentInformationHelper.unregisterListener(PaymentInformation.class
				.getCanonicalName());
		mEventHelper.unregisterListener(Event.class.getCanonicalName());
		mRegistrationStateHelper.unregisterListener(RegistrationState.class
				.getCanonicalName());
		super.onPause();
	}

	private void setupBasicGui() {
		setContentView(R.layout.activity_event_details);

		/* Configure the ActionBar */
		setActionBarTitle(R.string.app_name);
		setActionBarHomeAction(new Intent(this, HomeActivity.class));

		/* Get the layout components references */
		tvRegState = (TextView) findViewById(R.id.tvRegistrationState);
		tvEventName = (TextView) findViewById(R.id.tvEventName);
		tvStartDate = (TextView) findViewById(R.id.tvEventStartDate);
		tvEndDate = (TextView) findViewById(R.id.tvEventEndDate);
		tvRegStartDate = (TextView) findViewById(R.id.tvEventRegistartionStart);
		tvRegEndDate = (TextView) findViewById(R.id.tvEventRegistrationEnd);
		tbPaymentInfo = (TableLayout) findViewById(R.id.tbPaymentInformations);
		tbStornoInfo = (TableLayout) findViewById(R.id.tbStornoInformations);
		btRegister = (Button) findViewById(R.id.btRegister);

		switch (mInformationToShow) {
		case SHOW_EVENT_BASIC_INFORMATIONS:
			btRegister.setVisibility(View.GONE);
			tvRegState.setVisibility(View.GONE);
			break;
		case SHOW_EVENT_WITH_REGISTARTION_STATE:
			btRegister.setVisibility(View.GONE);
			tvRegState.setVisibility(View.VISIBLE);
			break;
		case SHOW_EVENT_TO_REGISTER:
			btRegister.setVisibility(View.VISIBLE);
			btRegister.setOnClickListener(new btRegisteronClickListener());
			tvRegState.setVisibility(View.GONE);
			break;
		default:
			break;
		}
	}

	private Cursor queryEventData() {

		switch (mInformationToShow) {
		case SHOW_EVENT_BASIC_INFORMATIONS:
			mEvent = mEventHelper.getEventById(mEventId, null);
			break;
		case SHOW_EVENT_WITH_REGISTARTION_STATE:
			String whereClause = mWCB.buildWhereClause(
					RegistrationState.EVENT_ID, mEventId,
					WhereClauseBuilder.EQUAL);
			mEvent = mEventHelper.getUsersRegisteredEvents(null, whereClause,
					null);
			break;
		case SHOW_EVENT_TO_REGISTER:
			mEvent = mEventHelper.getEventById(mEventId, null);
			break;
		default:
			break;
		}

		return mEvent;
	}

	private void queryPaymentValues() {
		// Build the where clause for payment values
		String whereClause = mWCB.buildWhereClause(PaymentInformation.EVENT_ID,
				mEventId, WhereClauseBuilder.EQUAL);

		// Query for payment values
		mPaymentValues = mPaymentInformationHelper.getPaymentValues(null,
				whereClause, null);

		// Query for storno values
		mStornoValues = mPaymentInformationHelper.getStornoValues(null,
				whereClause, null);
	}

	/**
	 * Method fills the table with the rows
	 * 
	 * @param table
	 * @param c
	 */
	private void fillPaymentInfrormationsTable(TableLayout table, Cursor c) {
		table.removeAllViews();

		boolean moveSucceed = c.moveToFirst();
		int i = 0;

		while (moveSucceed) {
			// Inflate xml layout to new TableRow
			TableRow row = (TableRow) mLayoutInflater.inflate(
					R.layout.table_row_payment_information, null);
			TextView tvActiveFrom, tvActiveTo, tvValue;

			// Get the table rows child elements
			tvActiveFrom = (TextView) row
					.findViewById(R.id.tvPaymentValueStartDate);
			tvActiveTo = (TextView) row
					.findViewById(R.id.tvPaymentValueEndDate);
			tvValue = (TextView) row.findViewById(R.id.tvPaymentValue);

			// Fill the child views with the corresponding values
			Date activeFrom, activeTo = null;
			activeFrom = new Date(
					c.getLong(PaymentInformation.INDEX_ACTIVE_FROM));
			activeTo = new Date(c.getLong(PaymentInformation.INDEX_ACTIVE_TO));

			tvActiveFrom.setText(mSdf.format(activeFrom));
			tvActiveTo.setText(mSdf.format(activeTo));
			tvValue.setText(c.getString(PaymentInformation.INDEX_VALUE));

			// Add the row to the table
			table.addView(row, i);

			// Move on next row if exists
			i++;
			moveSucceed = c.moveToNext();
		}
	}

	private void fillEventInformations(Cursor event) {

		int indexEventName = event.getColumnIndex(Event.EVENT_NAME);
		int indexStartDate = event.getColumnIndex(Event.START_DATE);
		int indexEndDate = event.getColumnIndex(Event.END_DATE);
		int indexRegistrationStart = event
				.getColumnIndex(Event.REGISTRATION_START);
		int indexRegistrationEnd = event.getColumnIndex(Event.REGISTRATION_END);

		if (mEvent.moveToFirst()) {

			if (mInformationToShow == SHOW_EVENT_WITH_REGISTARTION_STATE) {
				int indexRegState = event
						.getColumnIndex(RegistrationState.STATE);
				int regState = event.getInt(indexRegState);

				switch (regState) {
				case 1:
					tvRegState
							.setBackgroundResource(R.color.reg_state_registered);
					tvRegState.setText(R.string.reg_state_registered);
					break;
				case 2:
					tvRegState.setBackgroundResource(R.color.reg_state_payed);
					tvRegState.setText(R.string.reg_state_payed);
					break;
				case 3:
					tvRegState
							.setBackgroundResource(R.color.reg_state_canceled);
					tvRegState.setText(R.string.reg_state_canceled);
					break;

				default:
					break;
				}
			}

			tvEventName.setText(mEvent.getString(indexEventName));
			tvStartDate.setText(mSdf.format(new Date(event
					.getLong(indexStartDate))));
			tvEndDate
					.setText(mSdf.format(new Date(event.getLong(indexEndDate))));
			tvRegStartDate.setText(mSdf.format(new Date(event
					.getLong(indexRegistrationStart))));
			tvRegEndDate.setText(mSdf.format(new Date(event
					.getLong(indexRegistrationEnd))));
		}
	}

	public class onEventInfromationUpdatedListener extends
			ActionBarOnDataUpdatedListener {

		public onEventInfromationUpdatedListener(ActionBar actionBar) {
			super(actionBar);
		}

		@Override
		protected void onFinished(Class objectId) {

			mPaymentInformationHelper.retrieveEventPaymentValues(mEventId);
			mPaymentInformationHelper.retrieveEventStornoValues(mEventId);

			mEvent.requery();
			super.onFinished(objectId);
		}

		protected void onError(Class objectClass) {

			Toast.makeText(EventDetailsActivity.this,
					R.string.retrieving_data_error, Toast.LENGTH_LONG).show();
			super.onFinished(objectClass);
		};
	}

	public class OnPaymentInformationUpdatedListener extends
			ActionBarOnDataUpdatedListener {

		public OnPaymentInformationUpdatedListener(ActionBar actionBar) {
			super(actionBar);
		}

		@Override
		protected void onFinished(Class objectClass) {
			// TODO
			mPaymentValues.requery();
			fillPaymentInfrormationsTable(tbPaymentInfo, mPaymentValues);
			mStornoValues.requery();
			fillPaymentInfrormationsTable(tbStornoInfo, mStornoValues);

			if (objectClass == PaymentValue.class) {
				mPaymentValues.requery();
				fillPaymentInfrormationsTable(tbPaymentInfo, mPaymentValues);
			} else if (objectClass == StornoValue.class) {
				mStornoValues.requery();
				fillPaymentInfrormationsTable(tbStornoInfo, mStornoValues);
			}

			super.onFinished(objectClass);
		}
	}

	public class onRegistrationStateUpdatedListener extends
			ActionBarOnDataUpdatedListener {

		public onRegistrationStateUpdatedListener(ActionBar actionBar) {
			super(actionBar);
		}

		@Override
		protected void onFinished(Class objectId) {

			super.onFinished(objectId);
			Intent intent = new Intent(getApplicationContext(),
					EventDetailsActivity.class);
			intent.putExtra("eventId", mEventId);
			intent.putExtra("userId", mUserId);
			intent.putExtra(EventDetailsActivity.ACTION_TYPE,
					EventDetailsActivity.SHOW_EVENT_WITH_REGISTARTION_STATE);
			startActivity(intent);
		}

		protected void onError(Class objectClass) {

			Toast.makeText(EventDetailsActivity.this,
					R.string.retrieving_data_error, Toast.LENGTH_LONG).show();
			super.onFinished(objectClass);
		};
	}

	public class btRegisteronClickListener implements OnClickListener {

		@Override
		public void onClick(View v) {
			mRegistrationStateHelper.registerUserOnEvent(mUserId, mEventId);
		}
	};

}
